package com.stars.config;

import com.stars.filter.JwtFilter;
import com.stars.module.login.service.impl.StarsRealm;
import lombok.Data;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;

import javax.servlet.Filter;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;

/**
 * @author : Rocks
 * @version : 1.0
 * @date : 2022/11/22 19:53
 * @description : shiro配置
 */
@Data
@Configuration
@ConfigurationProperties(prefix = "login")
public class ShiroConfig {

    public void init() {
        ignoreUrlList = new ArrayList<>();

        String[] split = ignoreUrl.split(",");
        for(String url : split){
            if(!StringUtils.hasLength(url)){
                continue;
            }
            ignoreUrlList.add(url);
        }

        //添加默认不需要拦截连接
        ignoreUrlList.add("/ctrl/starLogin/index");
        ignoreUrlList.add("/ctrl/starLogin/getPublicKey");
        ignoreUrlList.add("/ctrl/starLogin/captcha");
        ignoreUrlList.add("/ctrl/starLogin/doLogin");
        ignoreUrlList.add("/ctrl/test/**");
        ignoreUrlList.add("/ctrl/publish/**");
        ignoreUrlList.add("/ctrl/common/publish/**");
        ignoreUrlList.add("/ctrl/starCode/getCode");
        ignoreUrlList.add("/ctrl/router/getData");

    }

    /**
     * Create Security Manager 安全管理器，管理Realm数据源
     */
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager securityManager(@Qualifier("starsRealm") StarsRealm starsRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //向安全管理器注入自定义Realm
        securityManager.setRealm(starsRealm);
        //关闭ShiroSession，实现Shiro无状态
        DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
        DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
        defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
        subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
        securityManager.setSubjectDAO(subjectDAO);
        return securityManager;
    }

    @Bean
    ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
        this.init();
        //设置securityManager
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
        //自定义过滤器，JwtFilter
        LinkedHashMap<String, Filter> filterMap = new LinkedHashMap<>();
        filterMap.put("jwt",new JwtFilter());
        shiroFilterFactoryBean.setFilters(filterMap);

        //设置拦截器，使用LinkedHashMap保证Filter的有序性
        LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        //公共资源或登录接口，无需进入过滤器直接执行即可

        for (String ignore : ignoreUrlList){
            filterChainDefinitionMap.put(ignore,"anon");
        }

        filterChainDefinitionMap.put("/ctrl/**", "jwt");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }


    //开启Shiro注解支持
    /**
     * 如果userPrefix和proxyTargetClass都为false会导致 aop和shiro权限注解不兼容 资源报错404
     * 因此两个属性至少需要其中一个属性为true才可以
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }
    /**
     * 开启aop注解支持
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); // 这里需要注入 SecurityManger 安全管理器
        return authorizationAttributeSourceAdvisor;
    }

    private String ignoreUrl;
    private List<String> ignoreUrlList;

}
